//! Primary expression parsing

use super::control_flow::*;
use super::literals::*;
use super::Parser;
use crate::ast::expr::*;
use crate::ast::types::*;
use crate::error::{CompilerError, Result};
use crate::lexer::token::Token;

/// Parse primary expression
pub fn parse_primary(parser: &mut Parser) -> Result<Option<Expression>> {
    if parser.is_at_end() {
        return Ok(None);
    }

    if matches!(
        parser.peek().map(|t| &t.token),
        Some(Token::Identifier(_))
    ) && looks_like_struct_literal(parser)?
    {
        if let Some(struct_type) = super::super::type_parser::parse_type(parser)? {
            let struct_expr = super::parse_struct_literal_expression(parser, struct_type)?;
            return Ok(Some(struct_expr));
        }
    }

    match parser.peek() {
        Some(token) => match &token.token {
            // Literals
            Token::Integer(n) => {
                let n = *n;
                parser.advance()?;
                Ok(Some(Expression::Literal(Literal::Integer(n))))
            }
            Token::Float(f) => {
                let f = *f;
                parser.advance()?;
                Ok(Some(Expression::Literal(Literal::Float(f))))
            }
            Token::String(s) => {
                let s = s.clone();
                parser.advance()?;
                Ok(Some(Expression::Literal(Literal::String(s))))
            }
            Token::Char(c) => {
                let c = *c;
                parser.advance()?;
                Ok(Some(Expression::Literal(Literal::Char(c))))
            }
            Token::True => {
                parser.advance()?;
                Ok(Some(Expression::Literal(Literal::Boolean(true))))
            }
            Token::False => {
                parser.advance()?;
                Ok(Some(Expression::Literal(Literal::Boolean(false))))
            }
            Token::Nil => {
                parser.advance()?;
                Ok(Some(Expression::Literal(Literal::Null)))
            }

            // Identifiers
            Token::Identifier(name) => {
                let name = name.clone();
                let loc = parser.current_location();
                parser.advance()?;

                // Syntactic sugar: Transform Some/None/Ok/Err to Option::/Result:: paths
                // Some(v) -> Option::Some(v)
                // None -> Option::None()
                // Ok(v) -> Result::Ok(v)
                // Err(v) -> Result::Err(v)
                if (name == "Some" || name == "None") && !parser.check(&Token::ColonColon) {
                    // Transform to Option::Some or Option::None
                    return Ok(Some(Expression::Path(PathExpr {
                        segments: vec!["Option".to_string(), name],
                        location: loc,
                    })));
                } else if (name == "Ok" || name == "Err") && !parser.check(&Token::ColonColon) {
                    // Transform to Result::Ok or Result::Err
                    return Ok(Some(Expression::Path(PathExpr {
                        segments: vec!["Result".to_string(), name],
                        location: loc,
                    })));
                }

                // Check if this is a path expression (e.g., Status::Pending)
                if parser.check(&Token::ColonColon) {
                    let mut segments = vec![name];

                    while parser.consume(&Token::ColonColon)? {
                        if let Some(Token::Identifier(segment)) = parser.peek().map(|t| &t.token) {
                            segments.push(segment.clone());
                            parser.advance()?;
                        } else {
                            return Err(CompilerError::syntax(
                                parser.current_location().line,
                                parser.current_location().column,
                                "Expected identifier after '::'",
                            ));
                        }
                    }

                    return Ok(Some(Expression::Path(PathExpr {
                        segments,
                        location: loc,
                    })));
                }

                // Check if this is a dotted identifier (e.g., io.println) or field access
                let mut full_name = name;
                let mut is_field_access = false;

                while parser.consume(&Token::Dot)? {
                    if let Some(Token::Identifier(part)) = parser.peek().map(|t| &t.token) {
                        // Check if this is a field access (object.field) or dotted identifier (module.function)
                        // For now, we'll treat it as field access if the first part is a simple identifier
                        if !is_field_access && !full_name.contains('.') {
                            is_field_access = true;
                        }

                        if is_field_access {
                            // This is field access, create FieldAccess expression
                            let field_name = part.clone();
                            parser.advance()?;

                            // Create field access expression
                            let field_access = Expression::FieldAccess(FieldAccessExpr {
                                object: Box::new(Expression::Variable(full_name)),
                                field: field_name,
                                location: parser.current_location(),
                            });

                            return Ok(Some(field_access));
                        } else {
                            // This is dotted identifier (e.g., io.println)
                            full_name = format!("{}.{}", full_name, part);
                            parser.advance()?;
                        }
                    } else {
                        return Err(CompilerError::syntax(
                            parser.current_location().line,
                            parser.current_location().column,
                            "Expected identifier after '.'",
                        ));
                    }
                }

                // Check if this is a Go-style struct literal (TypeName{...})
                // We need to peek ahead to see if it's really a struct literal
                // A struct literal has the form: TypeName{field: value, ...} or TypeName{}
                // If it's just TypeName{expr}, it's NOT a struct literal
                if parser.check(&Token::LeftBrace) {
                    // Peek ahead to see if this looks like a struct literal
                    // Save current position in case we need to backtrack
                    let is_struct_literal = if let Some(next_token) = parser.peek_ahead(1) {
                        // If the next token after { is }, it's an empty struct literal
                        // If it's an identifier followed by :, it's a struct literal
                        matches!(next_token.token, Token::RightBrace)
                            || (matches!(next_token.token, Token::Identifier(_))
                                && parser
                                    .peek_ahead(2)
                                    .map_or(false, |t| matches!(t.token, Token::Colon)))
                    } else {
                        false
                    };

                    if is_struct_literal {
                        parser.consume(&Token::LeftBrace)?;
                        // Parse struct literal fields
                        let mut fields = Vec::new();

                        if !parser.check(&Token::RightBrace) {
                            loop {
                                if let Some(Token::Identifier(field_name)) =
                                    parser.peek().map(|t| &t.token)
                                {
                                    let name = field_name.clone();
                                    parser.advance()?;
                                    parser.expect(&Token::Colon)?;

                                    let value = super::parse_expression(parser)?;
                                    if let Some(value) = value {
                                        fields.push(FieldInit {
                                            name,
                                            value,
                                            location: parser.current_location(),
                                        });
                                    }
                                }

                                if !parser.consume(&Token::Comma)? {
                                    break;
                                }
                            }
                        }

                        parser.expect(&Token::RightBrace)?;

                        // Create struct type from identifier
                        let struct_type = Type::Struct(StructType {
                            name: full_name,
                            type_args: vec![],
                            location: parser.current_location(),
                        });

                        Ok(Some(Expression::Struct(StructExpr {
                            struct_type,
                            fields,
                            location: parser.current_location(),
                        })))
                    } else {
                        // Not a struct literal, just a variable
                        Ok(Some(Expression::Variable(full_name)))
                    }
                } else {
                    Ok(Some(Expression::Variable(full_name)))
                }
            }

            // Parenthesized expressions
            Token::LeftParen => {
                parser.advance()?;
                let expr = super::parse_expression(parser)?;
                parser.expect(&Token::RightParen)?;
                Ok(expr)
            }

            // Array/Slice literals
            Token::LeftBracket => {
                // Need to distinguish between array literal [1,2,3] and slice literal []int{1,2,3}
                // Peek ahead to check if this is a slice literal
                if let Some(next_token) = parser.peek_ahead(1) {
                    if matches!(next_token.token, Token::RightBracket) {
                        // This might be a slice literal []T{...}
                        // Try to parse as slice literal
                        parse_slice_literal(parser)
                    } else {
                        // This is an array literal [expr, ...]
                        parse_array_literal(parser)
                    }
                } else {
                    parse_array_literal(parser)
                }
            }

            // Map literals (Map<K, V>{...})
            Token::MapFull => parse_map_literal(parser),

            // Vector literals
            Token::VecFull => parse_slice_literal(parser),

            // Struct literals
            Token::Struct => parse_struct_literal(parser),

            // Lambda expressions
            Token::Fn => parse_lambda(parser),

            // Match expressions
            Token::Match => parse_match_expression(parser),

            // If expressions
            Token::If => parse_if_expression(parser),

            // For expressions
            Token::For => parse_for_expression(parser),

            // While expressions
            Token::While => parse_while_expression(parser),

            // Panic expressions
            Token::Panic => parse_panic_expression(parser),

            // Select expressions
            Token::Select => parse_select_expression(parser),

            // Go expressions
            Token::Go => parse_go_expression(parser),

            // New expressions
            Token::New => parse_new_expression(parser),

            // Reference counted object construction: Rc<T>{value}
            Token::Rc => parse_rc_expression(parser),

            _ => Ok(None),
        },
        None => Ok(None),
    }
}

/// Parse reference counted object construction: Rc<T>{value}
pub fn parse_rc_expression(parser: &mut Parser) -> Result<Option<Expression>> {
    let loc = parser.current_location();
    parser.expect(&Token::Rc)?;

    // Parse type argument: <T>
    parser.expect(&Token::Less)?;
    let inner_type = crate::parser::type_parser::parse_type(parser)?.ok_or_else(|| {
        CompilerError::syntax(
            parser.current_location().line,
            parser.current_location().column,
            "Expected type argument for Rc<T>",
        )
    })?;
    parser.expect(&Token::Greater)?;

    // Parse initializer if present: {value} or {field: value, ...}
    let initializer = if parser.consume(&Token::LeftBrace)? {
        if parser.check(&Token::RightBrace) {
            // Empty initializer: Rc<T>{}
            parser.advance()?;
            None
        } else {
            // Check if this is a struct literal (field: value) or just a value
            let is_struct_literal =
                if let Some(Token::Identifier(_)) = parser.peek().map(|t| &t.token) {
                    parser
                        .peek_ahead(1)
                        .map_or(false, |t| matches!(t.token, Token::Colon))
                } else {
                    false
                };

            if is_struct_literal {
                // Parse struct literal fields
                let mut fields = Vec::new();

                loop {
                    if let Some(Token::Identifier(field_name)) = parser.peek().map(|t| &t.token) {
                        let name = field_name.clone();
                        parser.advance()?;
                        parser.expect(&Token::Colon)?;

                        let value = super::parse_expression(parser)?;
                        if let Some(value) = value {
                            fields.push(FieldInit {
                                name,
                                value,
                                location: parser.current_location(),
                            });
                        }
                    }

                    if !parser.consume(&Token::Comma)? {
                        break;
                    }
                }

                parser.expect(&Token::RightBrace)?;

                // Create struct expression
                Some(Expression::Struct(StructExpr {
                    struct_type: inner_type.clone(),
                    fields,
                    location: loc,
                }))
            } else if matches!(inner_type, Type::Vec(_)) {
                // For slice types, parse as slice literal directly
                // Rc<Vec<int32>>{1, 2, 3} -> parse as slice literal
                let mut elements = Vec::new();

                loop {
                    if parser.check(&Token::RightBrace) {
                        break;
                    }

                    let element = super::parse_expression(parser)?;
                    if let Some(element) = element {
                        elements.push(element);
                    }

                    if !parser.consume(&Token::Comma)? {
                        break;
                    }
                }

                parser.expect(&Token::RightBrace)?;

                // Create slice expression
                // Extract element type from slice type
                let element_type = if let Type::Vec(vector_type) = &inner_type {
                    *vector_type.element_type.clone()
                } else {
                    return Err(CompilerError::internal("Expected slice type"));
                };

                Some(Expression::Slice(SliceExpr {
                    element_type,
                    elements,
                    capacity: None,
                    count: None,
                    location: loc,
                }))
            } else {
                // Parse the value expression
                let value = super::parse_expression(parser)?;
                parser.expect(&Token::RightBrace)?;
                value
            }
        }
    } else {
        None
    };

    Ok(Some(Expression::Rc(RcExpr {
        inner_type: Box::new(inner_type),
        initializer: initializer.map(Box::new),
        location: loc,
    })))
}

fn looks_like_struct_literal(parser: &mut Parser) -> Result<bool> {
    let mut offset = 1;

    loop {
        match parser.peek_ahead(offset).map(|t| &t.token) {
            Some(Token::ColonColon) => {
                offset += 1;
                if !matches!(
                    parser.peek_ahead(offset).map(|t| &t.token),
                    Some(Token::Identifier(_))
                ) {
                    return Ok(false);
                }
                offset += 1;
            }
            _ => break,
        }
    }

    if matches!(
        parser.peek_ahead(offset).map(|t| &t.token),
        Some(Token::Less)
    ) {
        let mut depth = 1;
        offset += 1;
        while let Some(tok) = parser.peek_ahead(offset) {
            match tok.token {
                Token::Less => depth += 1,
                Token::Greater => {
                    depth -= 1;
                    offset += 1;
                    if depth == 0 {
                        break;
                    } else {
                        continue;
                    }
                }
                Token::LeftBrace | Token::RightBrace | Token::LeftParen | Token::RightParen
                    if depth > 0 =>
                {
                    return Ok(false);
                }
                _ => {}
            }
            offset += 1;
        }
        if depth != 0 {
            return Ok(false);
        }
    }

    if !matches!(
        parser.peek_ahead(offset).map(|t| &t.token),
        Some(Token::LeftBrace)
    ) {
        return Ok(false);
    }

    // Look at the token following '{' to avoid confusing match statements with struct literals.
    match parser.peek_ahead(offset + 1).map(|t| &t.token) {
        Some(Token::RightBrace) => Ok(true),
        Some(Token::Identifier(_)) => Ok(
            parser
                .peek_ahead(offset + 2)
                .map_or(false, |t| matches!(t.token, Token::Colon)),
        ),
        _ => Ok(false),
    }
}
